<html>
<head>
<title>Remake de Fruity Frank - Version 0.15</title>
<style type="text/css">
span {
	font-family: 'Courier New';
	font-size: 10pt;
	color: #000000;
}
.SpanClass0 {
	color: #808080;
}
.SpanClass3 {
	color: #008080;
}
.SpanClass5 {
	font-weight: bold;
	color: #0000FF;
}
.SpanClass7 {
	color: #808080;
}
.SpanClass10 {
	font-weight: bold;
	color: #000080;
}
.SpanClass11 {
}
</style>
</head>
<body bgcolor="#FFFFFF">
<h2>Remake (parcial) de Fruity Frank... 15 - Colisiones por coordenadas</h2>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Sabemos c&oacute;mo comprobar colisiones usando nuestro &quot;mapa&quot; de juego. Es interesante como primera aproximaci&oacute;n, pero generalmente querremos algo &quot;m&aacute;s fino&quot;: que el movimiento vuelva a a ser suave (algo que haremos pronto) y que las colisiones se puedan comprobar antes, en cuanto un elemento &quot;roce&quot; al otro (eso s&iacute; que lo haremos ahora).</p>

<p>Vamos a mejorar las colisiones que se basan exactamente en posiciones del mapa, para ver una forma de comprobar colisiones entre dos im&aacute;genes. Aun as&iacute;, lo que haremos tampoco ser&aacute; perfecto: comprobaremos si el rect&aacute;ngulo de una imagen se solapa con el rect&aacute;ngulo de otra imagen, pero habitualmente esto ser&aacute; totalmente preciso, porque la mayor&iacute;a de im&aacute;genes (personaje, enemigos, frutas) no ocupan por completo su rect&aacute;ngulo, as&iacute; que puede que consideremos que ha habido una colisi&oacute;n cuando realmente se est&eacute;n solapando dos &quot;zonas negras&quot; de las im&aacute;genes.</p>

<p>Otras alternativas m&aacute;s precisas incluir&iacute;an el descomponer la imagen en una serie de rect&aacute;ngulos que s&iacute; contengan elementos visibles (lo que complicar&iacute;a la forma de comprobar colisiones), o bien mirar los p&iacute;xeles que se solapan para ver si son &quot;transparentes&quot;, y entonces no dar la colision como v&aacute;lida (lo que tambi&eacute;n complicar&iacute;a, adem&aacute;s de ralentizar ligeramente). Por ahora no afinaremos tanto, y nos quedaremos con una aproximaci&oacute;n m&aacute;s precisa que la de antes, que funcionar&aacute; cuando un enemigo no se encuentre justo en una casilla del mapa, sino pasando de una a otra, pero que tampoco es totalmente precisa, especialmente con personajes que tengan formas irregulares.</p>

<p>Una forma de comprobar si se solapan dos rect&aacute;ngulos es ver qu&eacute; ocurre con sus extremos: en horizontal, si el extremo izquierdo de una imagen est&aacute; m&aacute;s a la derecha que el extremo derecho de la otra, no se solapan; para que se solapen, el extremo derecho de una imagen (x1) debe ser estar a la izquierda del extremo izquierdo de la otra (x1 &lt; x2+ancho2), y ocurrir lo mismo a la inversa (x2 &lt; x1+ancho1), y algo similar debe ocurrir en vertical:</p>

<pre><code>if ((x2+an2 &gt; x1)
    &amp;&amp; (y2+al2 &gt; y1)
    &amp;&amp; (x1+an1 &gt; x2)
    &amp;&amp; (y1+al1 &gt; y2))
  colision = true;
else
  colision = false;</code></pre>

<p>Pero en nuestro caso, parte del trabajo ya est&aacute; hecho: esa comprobaci&oacute;n forma parte de la clase &quot;SdlN&quot;:</p>

<pre><code>public bool Colision(int x1, int y1, int an1, int al1,
  int x2, int y2, int an2, int al2) 
{      
  if ((x2+an2 &gt; x1)
      &amp;&amp; (y2+al2 &gt; y1)
      &amp;&amp; (x1+an1 &gt; x2)
      &amp;&amp; (y1+al1 &gt; y2))
    return true;
  else
    return false;
}</code></pre>

<p>De modo que si nuestro juego se apoya en SdlN, basta con que comprobemos las colisiones as&iacute;:</p>

<pre><code>if (Colision(enemigos[i].x, enemigos[i].y, 
      enemigos[i].ancho, enemigos[i].alto,
      posXPersonaje, posYPersonaje,
      anchoPersonaje, altoPersonaje) )
  enemigos[i].activo = false;</code></pre>

<p>En este caso, como primera aproximaci&oacute;n, pero que todav&iacute;a no sigue una l&oacute;gica de juego real, cada vez que tocamos un enemigo, &eacute;ste desaparece (activo = false). En un juego real, nuestro enemigo perder&iacute;a una vida y volver&iacute;amos a comenzar la partida en el nivel actual. Si la colisi&oacute;n fuera entre un disparo y un enemigo, deber&iacute;amos dibujar una explosi&oacute;n antes de hacerlo desaparecer. Esos detalles pertenecen a la l&oacute;gica de cada juego, y nos iremos acercando a ellos poco a poco.</p>

<p><br />De paso, vamos a hacer otra peque&ntilde;a mejora en esta versi&oacute;n: la l&iacute;nea superior, que muestra la puntuaci&oacute;n, el record y la cantidad de vidas que nos quedan, va a dejar de ser &quot;predibujada&quot;. En vez de cargar la imagen que contiene casi todo eso fijo, vamos a ser nosotros los que mostremos los puntos (ya lo hac&iacute;amos), el record (que era fijo), la cantidad de vidas (aunque todav&iacute;a no nos puedan matar nuestros enemigos) y un recuadro alrededor de todo ello:</p>

<pre><code>// Tabla de records y vidas restantes
RectanguloRGBA(15,45,625,80, // Marco para records
  255, 109, 8,  // Naranja
  255); // Opaco        
EscribirTextoOculta(&quot;Puntos&quot;,20,60,
  0x88, 0xFF, 0xFF, fuenteSans14);
EscribirTextoOculta(puntos.ToString(&quot;000000&quot;),70,60,
  0xFF, 0xFF, 0x88, fuenteSans14);
EscribirTextoOculta(&quot;Mejor puntuac&quot;,200,60,
  0x88, 0xFF, 0xFF, fuenteSans14);
EscribirTextoOculta(mejorPunt.ToString(&quot;000000&quot;),300,60,
  0xFF, 0xFF, 0x88, fuenteSans14);
EscribirTextoOculta(&quot;Vidas&quot;,450,60,
  0x88, 0xFF, 0xFF, fuenteSans14);
for (i=0; i&lt;vidas-1; i++)
  DibujarImagenOculta(personajeD, (short)(490+i*30),48);</code></pre>

<p>(Por supuesto, esto supone algunos peque&ntilde;os cambios en el juego, como a&ntilde;adir la variable &quot;vidas&quot; o la variable &quot;mejorPunt&quot;).</p>


<p>Para m&aacute;s detalles, puedes ver todo el proyecto en: <a href="http://code.google.com/p/fruityfrank"> code.google.com/p/fruityfrank</a></p>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
